package com.yycx.module.bus.provider.service.impl;

import cn.hutool.extra.pinyin.PinyinUtil;
import cn.hutool.extra.pinyin.engine.pinyin4j.Pinyin4jEngine;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yycx.common.constants.CommonConstants;
import com.yycx.common.mybatis.base.service.impl.BaseServiceImpl;
import com.yycx.common.base.entity.EntityMap;
import com.yycx.common.mybatis.model.ResultBody;
import com.yycx.common.mybatis.query.CriteriaQuery;
import com.yycx.common.mybatis.query.CriteriaSave;
import com.yycx.common.mybatis.query.CriteriaUpdate;
import com.yycx.common.security.OpenHelper;
import com.yycx.common.security.OpenUser;
import com.yycx.common.utils.ApiAssert;
import com.yycx.common.base.utils.FlymeUtils;
import com.yycx.common.utils.DateUtils;
import com.yycx.module.bus.client.entity.*;
import com.yycx.module.bus.client.entity.hy.HyOrder;
import com.yycx.module.bus.provider.handler.haiying.BusinessUtils;
import com.yycx.module.bus.provider.mapper.BusCustomMapper;
import com.yycx.module.bus.provider.service.BusCustomAddressService;
import com.yycx.module.bus.provider.service.BusCustomBalanceService;
import com.yycx.module.bus.provider.service.BusCustomService;
import com.yycx.module.bus.provider.service.hy.HyRemoteOrderService;
import com.yycx.module.system.client.entity.SysCompany;
import com.yycx.module.system.client.entity.SysOrganization;
import com.yycx.module.system.provider.service.SysCompanyService;
import com.yycx.module.system.provider.service.SysOrganizationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Locale;

/**
 * 购货方接口实现类
 *
 * @author flyme
 * @date 2020-08-01
 */
@Service
public class BusCustomServiceImpl extends BaseServiceImpl<BusCustomMapper, BusCustom> implements BusCustomService {

    @Resource
    private SysOrganizationService organizationService;

    @Resource
    private SysCompanyService companyService;

    @Resource
    private BusCustomAddressService customAddressService;

    @Resource
    private HyRemoteOrderService hyRemoteOrderService;

    @Autowired
    @Lazy
    private BusCustomBalanceService customBalanceService;

    @Autowired
    @Lazy
    private BusinessUtils businessUtils;


    @Override
    public ResultBody beforeAdd(CriteriaSave cs, BusCustom custom, EntityMap extra) {
        CriteriaQuery cq = new CriteriaQuery(BusCustom.class);
        Long companyId = OpenHelper.getCompanyId();
        SysCompany company = companyService.getById(companyId);
        SysOrganization organization = organizationService.getById(company.getOrganizationId());
        Long organizationId = organization.getOrganizationId();
        Long n = count(cq.eq(true, "customName", custom.getCustomName()).eq(true, "companyId", companyId).eq(true, "organizationId", organizationId));
        ApiAssert.lezero("客户名称已存在", n.intValue());
        custom.setCustomState(CommonConstants.ENABLED);
        custom.setCompanyId(companyId);
        custom.setAllowJs(CommonConstants.DISABLED);
        custom.setOrganizationId(organizationId);
        return ResultBody.ok();
    }

    @Override
    public ResultBody afterAdd(CriteriaSave cs, BusCustom busCustom, EntityMap extra) {
        String address1 = cs.getParams("address1");
        String userName1 = cs.getParams("userName1");
        String telephone1 = cs.getParams("telephone1");
        String address2 = cs.getParams("address2");
        String userName2 = cs.getParams("userName2");
        String telephone2 = cs.getParams("telephone2");
        if (FlymeUtils.isNotEmpty(address1) && FlymeUtils.isNotEmpty(userName1)) {
            BusCustomAddress customAddress = new BusCustomAddress();
            customAddress.setAddress(address1);
            customAddress.setUserName(userName1);
            customAddress.setCustomId(busCustom.getCustomId());
            customAddress.setTelephone(telephone1);
            customAddress.setAddressType(1);
            customAddress.setState(1);
            customAddressService.saveOrUpdate(customAddress);
        }
        if (FlymeUtils.isNotEmpty(address2) && FlymeUtils.isNotEmpty(userName2)) {
            BusCustomAddress customAddress = new BusCustomAddress();
            customAddress.setAddress(address2);
            customAddress.setCustomId(busCustom.getCustomId());
            customAddress.setUserName(userName2);
            customAddress.setTelephone(telephone2);
            customAddress.setAddressType(2);
            customAddress.setState(1);
            customAddressService.saveOrUpdate(customAddress);
        }
        return super.afterAdd(cs, busCustom, extra);
    }

    @Override
    public ResultBody afterEdit(CriteriaUpdate cu, BusCustom busCustom, EntityMap extra) {
        BigDecimal goodsAmount = cu.getBigDecimal("goodsAmount", new BigDecimal("0"));
        Long customId = busCustom.getCustomId();
        customBalanceService.saveHkCustomBalance(customId, goodsAmount);
        return super.afterEdit(cu, busCustom, extra);
    }

    @Override
    public void afterGet(CriteriaQuery cq, EntityMap result) {
        Long customId = result.getLong("customId");
        Long companyId = result.getLong("companyId");
        super.afterGet(cq, result);
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public ResultBody beforePageList(CriteriaQuery<BusCustom> cq, BusCustom custom, EntityMap requestMap) {
        Long companyId = OpenHelper.getCompanyId();
        String customName = cq.getParams("customName");
        cq.select(BusCustom.class, "*");
        cq.select(SysOrganization.class, "organizationName");
        cq.select(SysCompany.class, "companyName");
        if (FlymeUtils.isNotEmpty(customName)) {
            String pinyin = PinyinUtil.getFirstLetter(customName, "").toUpperCase();
            cq.and(e -> e.like("customName", customName).or().likeRight("customNamePinYin", pinyin));
        }
        cq.eq(BusCustom.class, "companyId", companyId);
        cq.eq(BusCustom.class, "organizationId");
        cq.orderByAsc("custom.customName");
        cq.createJoin(SysCompany.class);
        cq.createJoin(SysOrganization.class);
        return ResultBody.ok();
    }

    @Override
    public List<EntityMap> afterPageList(CriteriaQuery<BusCustom> cq, List<EntityMap> data, ResultBody resultBody) {

        return super.afterPageList(cq, data, resultBody);
    }

    @Override
    public ResultBody beforeListEntityMap(CriteriaQuery<BusCustom> cq, BusCustom custom, EntityMap requestMap) {
        cq.eq(SysCompany.class, "companyId", OpenHelper.getCompanyId());
        cq.eq(BusCustom.class, "customState", CommonConstants.ENABLED);
        cq.createJoin(SysCompany.class);
        return super.beforeListEntityMap(cq, custom, requestMap);
    }

    @Override
    public List<BusCustom> listByName(String keyword) {
        CriteriaQuery cq = new CriteriaQuery(BusCustom.class);
        cq.eq("companyId", OpenHelper.getCompanyId());
        if (FlymeUtils.isNotEmpty(keyword)) {
            cq.like("customName", keyword);
        }
        cq.eq("customState", CommonConstants.ENABLED);
        cq.createJoin(SysCompany.class);
        cq.limit(20);
        return list(cq);
    }


    @Override
    public List<EntityMap> selectAreaName() {
        CriteriaQuery<BusCustom> cq = new CriteriaQuery(BusCustom.class);
        cq.select("areaName", "customId");
        cq.eq("companyId", OpenHelper.getCompanyId());
        cq.groupBy("areaName");
        cq.orderByAsc("areaName");
        return selectEntityMap(cq);
    }

    public BusCustom getByCustomCode(String customCode, Long companyId) {
        return getOne(new QueryWrapper<BusCustom>().lambda().eq(BusCustom::getCompanyId, companyId).eq(BusCustom::getCustomCode, customCode));
    }

    @Override
    @DSTransactional
    @DS("master")
    @Async("voucherExecutor")
    public void syncHyData(OpenUser openUser) {
        Long companyId = openUser.getCompanyId();
        syncHyCustom(companyId);
    }

    @Override
    public void syncHyCustom(SysCompany company) {
        syncHyCustom(company.getCompanyId());
    }

    @Override
    public void syncHyCustom(Long companyId) {
        Long organizationId = OpenHelper.getOrganizationId();
        String dbName = businessUtils.getDbName(companyId);
        ApiAssert.isNotEmpty("账套实例未配置", dbName);
        Date lastUpdate = DateUtils.addDays(DateUtils.getNowDate(), -4);
        EntityMap params = new EntityMap();
        params.put("lastUpdateDate", lastUpdate);
        List<EntityMap> deptList = hyRemoteOrderService.selectHasUpdateHyCustomList(dbName, params);
        for (EntityMap entityMap : deptList) {
            String customCode = entityMap.get("customCode");
            String customName = entityMap.get("customName");
            String linkMan = entityMap.get("linkMan");
            String telephone = entityMap.get("telephone");
            String customNamePinYin = entityMap.get("customNamePinYin");
            String areaCode = entityMap.get("sendAreaId");
            String sendArea = entityMap.get("sendArea");
            Date ypDate = entityMap.get("ypDate");
            Date zlDate = entityMap.get("zlDate");
            Date sqDate = entityMap.get("sqDate");
            Date sfzDate = entityMap.get("sfzDate");
            Date zbDate = entityMap.get("zbDate");
            Date qxDate = entityMap.get("qxDate");
            Date ngDate = entityMap.get("ngDate");
            Date zzDate = entityMap.get("zzDate");
            BusCustom custom = getByCustomCode(customCode, companyId);
            if (FlymeUtils.isEmpty(custom)) {
                custom = new BusCustom();
                custom.setCompanyId(companyId);
                custom.setOrganizationId(organizationId);
            }
            custom.setCustomCode(customCode);
            custom.setCustomName(customName);
            custom.setCustomNamePinYin(customNamePinYin);
            custom.setAllowJs(0);
            custom.setLinkMan(linkMan);
            custom.setTelephone(telephone);
            custom.setAreaName(sendArea);
            custom.setSettleType(false);
            custom.setAreaCode(areaCode);
            custom.setCustomState(CommonConstants.ENABLED);
            custom.setYpDate(ypDate);
            custom.setZlDate(zlDate);
            custom.setSqDate(sqDate);
            custom.setZbDate(zbDate);
            custom.setQxDate(qxDate);
            custom.setNgDate(ngDate);
            custom.setZzDate(zzDate);
            custom.setSfzDate(sfzDate);
            String ckAddress = entityMap.get("ckAddress");
            String userName = entityMap.get("userName");
            String linkTel = entityMap.get("linkTel");
            custom.setCkAddress(ckAddress);
            custom.setShTelephone(linkTel);
            custom.setShUserName(userName);
            saveOrUpdate(custom);
            Long customId = custom.getCustomId();
            if (FlymeUtils.isNotEmpty(ckAddress)) {
                saveCustomAddress(customCode, ckAddress, userName, customId, customCode, companyId);
            }
            syncCustomAddress(dbName, customCode, userName, ckAddress, customId, companyId);
        }
    }

    @DSTransactional
    @DS("master")
    @Override
    public BusCustom syncBusCustom(String dbName, String customCode, Long companyId) {
        EntityMap entityMap = hyRemoteOrderService.selectHyCustom(dbName, customCode);
        if (FlymeUtils.isNotEmpty(entityMap)) {
            String customName = entityMap.get("customName");
            String linkMan = entityMap.get("linkMan");
            String telephone = entityMap.get("telephone");
            String customNamePinYin = entityMap.get("customNamePinYin");
            String areaCode = entityMap.get("sendAreaId");
            String sendArea = entityMap.get("sendArea");
            Date ypDate = entityMap.get("ypDate");
            Date zlDate = entityMap.get("zlDate");
            Date sqDate = entityMap.get("sqDate");
            Date sfzDate = entityMap.get("sfzDate");
            Date zbDate = entityMap.get("zbDate");
            Date qxDate = entityMap.get("qxDate");
            Date ngDate = entityMap.get("ngDate");
            Date zzDate = entityMap.get("zzDate");
            BusCustom custom = getByCustomCode(customCode, companyId);
            if (FlymeUtils.isEmpty(custom)) {
                custom = new BusCustom();
                custom.setCompanyId(companyId);
            }
            custom.setAreaCode(areaCode);
            custom.setCustomCode(customCode);
            custom.setCustomName(customName);
            custom.setCustomNamePinYin(customNamePinYin);
            custom.setAllowJs(0);
            custom.setLinkMan(linkMan);
            custom.setTelephone(telephone);
            custom.setSettleType(false);
            custom.setCustomState(CommonConstants.ENABLED);
            custom.setYpDate(ypDate);
            custom.setZlDate(zlDate);
            custom.setAreaName(sendArea);
            custom.setSqDate(sqDate);
            custom.setZbDate(zbDate);
            custom.setQxDate(qxDate);
            custom.setNgDate(ngDate);
            custom.setZzDate(zzDate);
            custom.setSfzDate(sfzDate);
            String ckAddress = entityMap.get("ckAddress");
            String userName = entityMap.get("userName");
            String linkTel = entityMap.get("linkTel");
            custom.setCkAddress(ckAddress);
            custom.setShTelephone(linkTel);
            custom.setShUserName(userName);
            saveOrUpdate(custom);
            Long customId = custom.getCustomId();
            if (FlymeUtils.isNotEmpty(ckAddress)) {
                saveCustomAddress(customCode, ckAddress, userName, customId, customCode, companyId);
            }
            syncCustomAddress(dbName, customCode, userName, ckAddress, customId, companyId);
            return custom;
        }
        return null;
    }

    @Override
    @DSTransactional
    @DS("master")
    public void syncCustomAddress(String customCode) {
        Long companyId = OpenHelper.getCompanyId();
        SysCompany company = companyService.getById(companyId);
        BusCustom custom = getByCustomCode(customCode, companyId);
        Long customId = null;
        if (FlymeUtils.isNotEmpty(custom)) {
            customId = custom.getCustomId();
        }
        String dbName = "";
        if (FlymeUtils.isNotEmpty(company)) {
            dbName = company.getBusinessScope();
        }
        EntityMap check = hyRemoteOrderService.selectHyCustom(dbName, customCode);
        if (FlymeUtils.isNotEmpty(custom)) {
            String ckAddress = check.get("ckAddress");
            String userName = check.get("userName");
            String linkTel = check.get("linkTel");
            saveCustomAddress(customCode, ckAddress, userName, customId, linkTel, companyId);
            syncCustomAddress(dbName, customCode, userName, ckAddress, customId, companyId);
        }
    }

    @Override
    public BusCustom selectByCustomCode(String customCode, Long companyId) {
        CriteriaQuery cq = new CriteriaQuery(BusCustom.class);
        cq.eq(true, "customCode", customCode);
        cq.eq(true, "companyId", companyId);
        return getOne(cq, false);
    }

    @Override
    public BusCustom selectByCustomName(String customName, Long companyId) {
        CriteriaQuery<BusCustom> cq = new CriteriaQuery(BusCustom.class);
        cq.and(e -> e.eq("customName", customName).or().eq("customName", customName + "."));
        cq.eq(true, "companyId", companyId);
        return getOne(cq, false);
    }


    /**
     * 同步客商资料_收货地址表中的地址
     *
     * @param dbName
     * @param customCode
     * @param customId
     * @param userName
     * @param ckAddress
     * @param companyId
     */
    private void syncCustomAddress(String dbName, String customCode, String userName, String ckAddress, Long customId, Long companyId) {
        List<EntityMap> addressList = hyRemoteOrderService.selectHyCustomAddress(dbName, customCode);
        if (FlymeUtils.isNotEmpty(addressList)) {
            for (EntityMap map : addressList) {
                String address = map.get("address", "");
                String name = map.get("userName", "");
                String tel = map.get("telephone");
                if (!address.equals(ckAddress)) {
                    saveCustomAddress(customCode, address, name, customId, tel, companyId);
                }
            }
        }
    }

    /**
     * 保存收货地址
     *
     * @param customCode
     * @param ckAddress
     * @param userName
     * @param customId
     * @param linkTel
     * @param companyId
     */
    private void saveCustomAddress(String customCode, String ckAddress, String userName, Long customId, String linkTel, Long companyId) {
        BusCustomAddress customAddress = customAddressService.getByCustomCodeAndName(customCode, ckAddress, userName, companyId);
        if (FlymeUtils.isEmpty(customAddress)) {
            customAddress = new BusCustomAddress();
            customAddress.setCustomCode(customCode);
        }
        customAddress.setCustomId(customId);
        customAddress.setUserName(userName);
        customAddress.setTelephone(linkTel);
        customAddress.setAddress(ckAddress);
        customAddress.setCompanyId(companyId);
        customAddress.setAddressType(1);
        customAddress.setState(CommonConstants.ENABLED);
        customAddressService.saveOrUpdate(customAddress);
    }


    @Override
    public List<EntityMap> selectTop20HyCustomList(String title) {
        Long companyId = OpenHelper.getCompanyId();
        SysCompany company = companyService.getById(companyId);
        ApiAssert.isNotEmpty("账套信息不存在", company);
        String dbName = company.getBusinessScope();
        ApiAssert.isNotEmpty("账套实例未配置", dbName);
        if (FlymeUtils.isNotEmpty(title)) {
            title = title.toUpperCase();
        }
        List<EntityMap> list = hyRemoteOrderService.selectTop20HyCustomList(dbName, title);
        return list;
    }
}
